#pragma once
#include <sw/redis++/redis++.h>

namespace im
{
    using RedisPtr = std::shared_ptr<sw::redis::Redis>;
    class RedisClientFactory{
    public:
        static RedisPtr create(const std::string &host, int port, int db, bool keep_alive){
            sw::redis::ConnectionOptions opts;
            opts.host = host;
            opts.port = port;
            opts.db = db;
            opts.keep_alive = keep_alive;
            return std::make_shared<sw::redis::Redis>(opts);
        }
    };

    class Session{
    public:
        using ptr = std::shared_ptr<Session>;
        Session(const RedisPtr& client):_redis_client(client){}

        bool append(const std::string& session_id, const std::string uid){
            return _redis_client->set(session_id, uid);
        }
        long long remove(const std::string& session_id){
            return _redis_client->del(session_id);
        }
        sw::redis::OptionalString uid(const std::string &ssid) {
            return _redis_client->get(ssid);
        }
    private:
        RedisPtr _redis_client;
    };

    class Status{
    public:
        using ptr = std::shared_ptr<Status>;
        Status(const RedisPtr& client):_redis_client(client){}
        
        bool append(const std::string uid){
            return _redis_client->set(uid, "");
        }
        long long remove(const std::string& uid){
            return _redis_client->del(uid);
        }
        bool exists(const std::string &uid) {
            if(_redis_client->get(uid))
                return true;
            return false;
        }
    private:
        RedisPtr _redis_client;
    };

    class VerifyCode{
    public:
        using ptr = std::shared_ptr<VerifyCode>;
        VerifyCode(const RedisPtr& client):_redis_client(client){}
        
        bool append(const std::string& code_id, const std::string code, 
                    const std::chrono::milliseconds& timeout = std::chrono::milliseconds(5*60*1000)){
            return _redis_client->set(code_id, code, timeout);
        }

        long long remove(const std::string& code_id){
            return _redis_client->del(code_id);
        }
        sw::redis::OptionalString code(const std::string &cid)  {
            return _redis_client->get(cid);
        }
    private:
        RedisPtr _redis_client;
    };
} // namespace im
